<template>
  <div class="main">

    <!-- v-model="active"是控制默认选择 在data(){}里面控制 -->
    <van-tabs v-model="active" swipeable>
      <!-- 把用户频道数据 渲染到页面上 -->
      <van-tab :key="item.id" v-for="item in channels" :title="item.name">
        <div class="scroll-wrapper">
          <!-- 添加 上拉菜单刷新 -->
          <!--isLoading 是控制上拉的状态为 布尔控制 -->
          <!-- @refresh是声明上拉刷新数据方法 -->
          <van-pull-refresh v-model="activeChannel.isLoading" @refresh="onRefresh" :success-text="activeChannel.pullText">
            <!-- 添加 滑动下拉的数据 -->
            <!-- :finished 是列表加载完成的标志 布尔控制 loading 是下拉状态为 布尔控制  -->
            <!-- @load是声明下拉获取数据方法-->
            <van-list v-model="activeChannel.loading" :finished="activeChannel.finished" finished-text="没有更多了" @load="onLoad">
              <!-- 把数据渲染到页面上的框架 -->
              <van-cell @click='$router.push("/detail?id="+item.art_id.toString())' v-for="item in activeChannel.articles" :key="item.art_id.toString()">
                <!-- 把数据渲染到页面上内容 -->
                <div class="article_item">
                  <h3 class="van-ellipsis">{{item.title}}</h3>
                  <div class="img_box">
                    <!-- 进行判断 如果 数据图片为3张时候 把类名设置为 w33 如果为1张时候 把类名设置为w100 -->
                    <!-- 循环遍历 v-for 获取储存的数组中的数据 -->
                    <van-image lazy-load :class='[{w33: item.cover.type === 3}, {w100: item.cover.type === 1}]' :key='index' v-for='(img, index) in item.cover.images' fit="cover" :src="img" />
                  </div>
                  <div class="info_box">
                    <!-- 通过Vue 方法 循环遍历打印到页面上 -->
                    <span>{{item.aut_name}}</span>
                    <span>{{item.comm_count}} 评论</span>
                    <span>{{item.pubdate|formatTime}}</span>
                    <span class="close">
                      <!-- ?设置点击显示弹窗事件 点击后设置为true 并且获取文章对应的id值 -->
                      <van-icon @click.stop='handleOpen(item.art_id)' name="cross"></van-icon>
                    </span>
                  </div>
                </div>
              </van-cell>
            </van-list>
          </van-pull-refresh>
        </div>
      </van-tab>
    </van-tabs>
    <span class="bar_btn">
      <van-icon @click='handleEdit' name="wap-nav"></van-icon>
    </span>
    <!-- ?添加更多操作组件 -->
    <!-- <more-action :value='isShow' @event-close='handleClose'></more-action> -->
    <!-- <more-action :value='isShow' @input='handleClose'></more-action> -->
    <!-- $event 在原生DOM事件中指的是事件对象 -->
    <!-- $event 在自定义事件中指的是传递的数据 -->
    <!-- <more-action :value='isShow' @input='isShow=$event'></more-action> -->

    <!-- ?当isShow被点击按钮点击后变为 true显示组件
          举报内容组件 @on-success='handleDislike' 接收子组件传回的图书id值-->
    <MoreAction v-model='isShow' :article-id='articleId' @on-success='handleDislike'></MoreAction>
    <!-- <MoreAction v-model='isShow'></MoreAction> -->
    <!-- ?编辑频道组件 接收子组件传来的数据 -->
    <ChannelEdit @addChannel='addChannel' @delChannel='delChannel' v-model='isEdit' :channels='channels' :activeindex.sync='active'></ChannelEdit>
  </div>
</template>
<script>
// ? 导入弹窗的组件
import MoreAction from '../../components/MoreAction'
// ? 导入 频道编辑操作组件
import ChannelEdit from '../../components/ChannelEdit'
// ! 1. 导入不同用户的频道数据
import { getAllChannels } from '../../api/channel'
// ! 2. 导入 频道切换文章列表的 api
import { getArticles } from '../../api/article'

export default {
  components: {
    // ? 导入弹窗举报关闭模板
    MoreAction,
    // ? 导入频道组件模板
    ChannelEdit
  },
  data () {
    return {
      // ? 控制编辑频道弹窗的显示和隐藏
      isEdit: false,
      // 创建一个点击后 获取文章id的对象
      articleId: -1,
      // ? Vant中提供弹窗属性(默认不显示false 点击后再显示) 需要在 data中设置
      isShow: false,
      // 控制Tab当前选中的条目
      active: 0,
      // 列表数据加载过程的状态位(加载的过程 会自动修改为true 但是渲染完毕后 需要手动修改false)
      loading: false,
      // 列表加载完成的标志(加载的结束 设置指定数值 加载到一定数目结束加载 需要手动修改true)
      finished: false,
      // 列表数组
      list: [],
      // 下拉刷新状态位
      isLoading: false,
      // 设置刷新提示
      pullText: '刷新成功',
      // ~ 设置函数节流
      throttle: false,
      // ! 3. 设置一个保存频道数据的数组
      channels: []
    }
  },
  computed: {
    //! 9. 当前激活的频道（data中添加active索引数据）
    activeChannel () {
      //! 10. 选中哪个channels频道 获取 其匹配的 active的条目
      return this.channels[this.active] //! 获取的是对象格式
    }
  },
  // ! 11. 生命周期 页面加载时候 添加并获取数据(需要设置)
  async created () {
    // ~ 接口调用是异步的
    // ~ 先要获取频道数据 并且添加频道关联文章列表属性名 再调用频道关联 动态切换文章列表方法
    await this.getAllChannels() //! 获取用户的频道数据并且添加切换根据属性名
    this.handleDislike()
  },
  methods: {
    // ! 4. 获取用户的频道数据并且添加切换文章列表根据的属性名 ----------------------
    async getAllChannels () {
      // ! 5. 调用获取用户频道数据的专用组件
      const ret = await getAllChannels()
      // ! 6. 保存服务器返回的数据
      // ! 7. 利用map方法 给频道数据添加新的属性名 关联文章列表
      this.channels = ret.data.channels.map(item => {
        //! 8. 作为频道切换的根据 自定义属性名  匹配 列表文章切换属性
        return {
          // ! 频道的id
          id: item.id,
          // ! 频道的标签名称
          name: item.name,
          // ! 文章列表加载状态
          loading: false,
          // ! 下拉刷新的完成状态
          isLoading: false,
          // ! 上拉列表加载完成的标志
          finished: false,
          // ! 下拉刷新完成的提示信息
          pullText: '加载成功',
          // ! 时间戳，用于实现列表的分页查询
          timestamp: +new Date(), //! 把时间设置为毫秒数 +
          // ! 获取文章列表储存
          articles: []
        }
      })
    },
    //! 12. 每次触发动态加载一页新的数据（下滑到底部时触发）------------------------
    //! 频道列表关联文章列表切换  并实现下滑获取文章列表
    async onLoad () { //! 14. 需要设置 同步执行处理异步 使用 async await
      //! 13. 获取当前频道信息(map方法已经添加 相关频道信息 实现文章列表关联)
      const channel = this.activeChannel
      //! 14. 与文章列表数据进行比对 实现频道关联 动态切换文章列表 并且获取相应数据
      const ret = await getArticles(channel.id, channel.timestamp)
      //! 15. 把加载的单页数据添加到文章列表的数组中
      channel.articles.push(...ret.data.results)
      //! 16. 通知Vant-list 组件本次数据加载成功(Vant加载数据自动为 true 加载完毕后 手动设置false)
      channel.loading = false
      //! 17. 判断 是否获取完毕数据(通过时间戳 如果 后端不返回时间戳 说明已经获取完毕)
      if (ret.data.pre_timestamp) {
        //! 18. 如果后端返回有时间戳 说明还有数据 继续和后端交互时间戳 实现数据获取
        channel.timestamp = ret.data.pre_timestamp
      } else {
        //! 19. 如果不返回时间戳 说明没有数据 把Vant方法 结束加载 设置为 true 表示加载完成
        channel.finished = true
      }
    },

    //! 20. 更新数据 比对当前时间戳 获取更新后的数据 (实现 上滑 更新数据)分页 ---------------------
    async onRefresh () { //! 需要设置 同步执行处理异步 使用 async await
      //! 21. 获取当前频道信息(map方法已经添加 相关频道信息 实现文章列表关联)
      const channel = this.activeChannel
      //! 22. 重置时间戳(获取当前时间戳 比对服务器的时间戳 实现更新)
      channel.timestamp = +new Date()
      //! 23.  与文章列表数据进行比对 实现频道关联 动态切换文章列表 并且获取刷新后相应数据
      const ret = await getArticles(channel.id, channel.timestamp)
      //! 需要把加载最新数据 覆盖当前文章列表 并且获取服务器最新的时间戳 如果没数据 啥也不做
      //! 24. 进行判断 查看服务器是否有更新数据
      if (ret.data.results.length > 0) {
        //! 25. 如果服务器有新的数据 那就覆盖当前储存数据的数组 实现更新
        channel.articles = ret.data.results
        //! 26. 如果服务器返回了时间戳 则替换当前数组的时间戳
        if (ret.data.pre_timestamp) {
          //! 把数组的时间戳 替换为服务器返回的新时间戳
          channel.timestamp = ret.data.pre_timestamp
        }
      } else {
        //! 27. 如果服务器没有更新数据 那么提示用户 没有数据更新 什么也不做
        channel.pullText = '没有数据更新'
        //! 优化提示
        channel.articles = []
        channel.timestamp = ret.data.pre_timestamp
        this.onLoad()
      }
      //! 28. 数据刷新完毕后 设置加载结束为 false 如果为true 则无法获取下滑刷新的数据
      channel.isLoading = false
      //! 29. 数据更新后 通知Vant-list 组件本次数据加载成功(Vant加载数据自动为 true 加载完毕后 手动设置false)
      channel.finished = false
    },
    // ? 控制更多操作组件显示(显示组件)
    handleOpen (id) {
      // ? 点击后 显示组件(false 变为 true) 传给子组件
      this.isShow = true
      // 记录文章的id
      this.articleId = id
    },
    // ? 控制更多操作组件显示(隐藏组件)
    handleClose (flag) {
      // ? 控制更多操作弹窗的关闭 (true 变为 false) 传给子组件
      this.isShow = flag
    },
    // 不敢兴趣的删除功能方法
    handleDislike (id) { // 接收子组件传回要删除的id值
      // 根据id删除该文章
      const index = this.activeChannel.articles.findIndex(item => {
        return item.art_id === id
      })
      // 根据索引删除数组的一个元素
      this.activeChannel.articles.splice(index, 1)
    },
    // ? 控制打开编辑频道弹窗
    handleEdit () {
      this.isEdit = true
    },
    // 接收子组件传来删除频道的id值 进行页面删除
    delChannel (id) {
      const index = this.channels.findIndex(item => {
        // 把页面上的频道列表 和 子组件传来的 频道id值 进行比对 findIndex方法 查询到其索引值进行删除
        return item.id === id
      })
      // 根据索引 删除对应的页面频道数据
      this.channels.splice(index, 1)
    },
    // 接收子组件传来的添加频道数据
    addChannel (channel) {
      // 把传来的数据 添加到页面频道数组里
      this.channels.push(channel)
    }
  }
}
</script>
<style lang="less" scoped>
.main {
  height: 100%;
  .van-tabs {
    height: 100%;
    display: flex;
    flex-direction: column;
    /deep/ .van-tabs__wrap {
      height: 72px;
      padding-right: 72px;
      .van-tab {
        line-height: 72px;
      }
      .van-tabs__line {
        background-color: #3296fa;
        height: 2px;
      }
    }
    // 修改Vant插件样式 需要用到/deep/ 防止修改失败
    /deep/ .van-tabs__content {
      flex: 1;
      overflow: hidden;
      .van-tab__pane {
        height: 100%;
        .scroll-wrapper {
          height: 100%;
          overflow-y: auto;
        }
      }
    }
  }
  .bar_btn {
    width: 72px;
    height: 70px;
    position: absolute;
    top: 0;
    right: 0;
    &::before {
      content: '';
      width: 100%;
      height: 100%;
      position: absolute;
      z-index: 999;
      box-shadow: 0 0 10px #999;
      transform: scale(1, 0.6);
    }
    .van-icon-wap-nav {
      width: 100%;
      height: 100%;
      background: #fff;
      text-align: center;
      line-height: 70px;
      position: relative;
      z-index: 1000;
      &::before {
        font-size: 40px;
      }
    }
  }
  .article_item {
    h3 {
      font-weight: normal;
      line-height: 2;
    }
    .img_box {
      display: flex;
      justify-content: space-between;
      .w33 {
        width: 33%;
        height: 180px;
      }
      .w100 {
        width: 100%;
        height: 360px;
      }
    }
    .info_box {
      color: #999;
      line-height: 2;
      position: relative;
      font-size: 24px;
      span {
        padding-right: 20px;
        &.close {
          border: 1px solid #ddd;
          border-radius: 4px;
          line-height: 30px;
          height: 24px;
          width: 32px;
          text-align: center;
          padding-right: 0;
          font-size: 16px;
          position: absolute;
          right: 0;
          top: 14px;
        }
      }
    }
  }
}
</style>
